import { Injectable } from '@nestjs/common';
import { RoleService } from '../role/role.service';
import { InjectRepository } from '@nestjs/typeorm';
import { MenuEntity } from './menu.entity';
import { Repository } from 'typeorm';
import { concat, isEmpty, uniq } from 'lodash';
import { ROOT_ROLE_ID } from '../constant/system.constant';
import { generatorRouters } from '~/utils/permission.util';

@Injectable()
export class MenuService {
  constructor(
    private roleService: RoleService,
    @InjectRepository(MenuEntity)
    private menuRepository: Repository<MenuEntity>
  ) {}

  async list(): Promise<MenuEntity[]> {
    const menus = await this.menuRepository.find();
    // const menuList = generatorMenu(menus);
    // if (!isEmpty(menuList)) {
    //   deleteEmptyChildren(menuList);
    //   return menuList;
    // }
    return menus;
  }

  /**
   * 根据角色获取所有菜单
   */
  async getMenus(uid: number) {
    const roleIds = await this.roleService.getRoleIdsByUser(uid);
    let menus: MenuEntity[] = [];

    if (isEmpty(roleIds)) return generatorRouters([]);

    if (this.roleService.hasAdminRole(roleIds)) {
      menus = await this.menuRepository.find({ order: { orderNo: 'ASC' } });
    } else {
      menus = await this.menuRepository
        .createQueryBuilder('menu')
        .innerJoinAndSelect('menu.roles', 'role')
        .andWhere('role.id IN (:...roleIds)', { roleIds })
        .orderBy('menu.order_no', 'ASC')
        .getMany();
    }

    const menuList = generatorRouters(menus);
    return menuList;
  }

  /**
   * 获取当前用户的所有权限
   */
  async getPermissions(uid: number): Promise<string[]> {
    const roleIds = await this.roleService.getRoleIdsByUser(uid);
    let permission: string[] = [];
    let result: any = null;
    let roleIdsToUse: number[] = [];
    if (this.roleService.hasAdminRole(roleIds)) {
      roleIdsToUse = [ROOT_ROLE_ID];
    } else {
      roleIdsToUse = roleIds;
    }
    result = await this.menuRepository
      .createQueryBuilder('menu')
      .innerJoinAndSelect('menu.roles', 'role')
      .andWhere('role.id IN (:...roleIds)', { roleIds: roleIdsToUse })
      .andWhere('menu.type IN (1,2)')
      .andWhere('menu.permission IS NOT NULL')
      .getMany();
    if (!isEmpty(result)) {
      result.forEach((e) => {
        if (e.permission) permission = concat(permission, e.permission.split(','));
      });
      permission = uniq(permission);
    }
    return permission;
  }
}
